package es.prodevelop.arport;

import java.io.IOException;

import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.view.WindowManager;
import android.widget.Toast;

import com.wikitude.architect.ArchitectUrlListener;
import com.wikitude.architect.ArchitectView;

/**
 * 
 * @author Wikitude
 * @date JAN 2012
 * 
 * @class ARBrowserActivity
 * 
 *        sample application to show how to use the ARchitect SDK loads simple
 *        pois via javascript into the ARchitect world and displays them
 *        accordingly displays a bubble with information about the selected poi
 *        on the screen and displays a detail page when the bubble is clicked
 *        uses Android's LocationManager to get updates on the user's location
 * 
 *        important is that the methods of the activity lifecycle are forwarded
 *        to the ArchitectView Important methods: onPostCreate() onResume()
 *        onPause() onDestroy() onLowMemory()
 * 
 *        Please also have a look at the application's Manifest and layout
 *        xml-file to see the permissions and requirements an activity using the
 *        SDK has to possess. (REF: ARchitect Documentation)
 */
public abstract class ARBrowserActivity extends Activity implements
		ArchitectUrlListener, LocationListener {

	/**
	 * sample location, you have to set up location-service your own way... this
	 * sample beams you to a fixed position in case you change these values you
	 * also need to adjust samplepois.json to run
	 * "SHOWCASE_TEST_JSSERVERREQUEST" properly
	 */
	// VALENCIA
	// public static float TEST_LATITUDE = 39.470059f;
	// public static float TEST_LONGITUDE = -0.375509f;
	// ALCASSER
	public static float TEST_LATITUDE = 39.368213f;
	public static float TEST_LONGITUDE = -0.444689f;
	public static float TEST_ALTITUDE = 0f;

	private String apiKey = "";

	private ArchitectView architectView;
	private LocationManager locManager;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// let the application be fullscreen
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);

		// check if the device fulfills the SDK'S minimum requirements
		if (!ArchitectView.isDeviceSupported(this)) {
			Toast.makeText(this, "minimum requirements not fulfilled",
					Toast.LENGTH_LONG).show();
			finish();
			return;
		}
		setContentView(R.layout.arport);

		// set the devices' volume control to music to be able to change the
		// volume of possible soundfiles to play
		// this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
		architectView = (ArchitectView) this.findViewById(R.id.architectView);
		// onCreate method for setting the license key for the SDK
		architectView.onCreate(apiKey);

		// in order to inform the ARchitect framework about the user's location
		// Androids LocationManager is used in this case
		// NOT USED IN THIS EXAMPLE
		locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		// locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
		// this);

		// If the GPS_PROVIDER is enable use it
		if (locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
			locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
					0, this);
		}
		// Otherwise, if the NETWORK_PROVIDER is enabled use it
		else if (locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
			if (wifiOrMobileProviderEnabled()) {
				locManager.requestLocationUpdates(
						LocationManager.NETWORK_PROVIDER, 0, 0, this);
			} else {
				Toast.makeText(
						this,
						"Habilita alguna de las conexiones para localizar su dispositivo (GPS/WIFI/3G)",
						Toast.LENGTH_LONG).show();
			}
		} else {
			Toast.makeText(
					this,
					"Habilita alguna de las conexiones para localizar su dispositivo (GPS/WIFI/3G)",
					Toast.LENGTH_LONG).show();
		}
	}

	@Override
	protected void onPostCreate(Bundle savedInstanceState) {
		super.onPostCreate(savedInstanceState);

		// IMPORTANT: creates ARchitect core modules
		if (architectView != null)
			architectView.onPostCreate();

		// register this activity as handler of "architectsdk://" urls
		architectView.registerUrlListener(this);

		try {
			loadARWorld();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	protected void onResume() {
		super.onResume();

		architectView.onResume();
		architectView.setLocation(TEST_LATITUDE, TEST_LONGITUDE, TEST_ALTITUDE,
				1f);
	}

	@Override
	protected void onPause() {
		super.onPause();
		if (architectView != null) {
			architectView.onPause();
		}
		// remove the automatic updates
		if (locManager != null) {
			locManager.removeUpdates(this);
		}
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();

		if (architectView != null) {
			architectView.onDestroy();
		}
	}

	@Override
	public void onLowMemory() {
		super.onLowMemory();

		if (architectView != null)
			architectView.onLowMemory();
	}

	/**
	 * listener method called when the location of the user has changed used for
	 * informing the ArchitectView about a new location of the user
	 */
	@Override
	public void onLocationChanged(Location loc) {
		// IMPORTANT:
		// use this method for informing the SDK about a location change by the
		// user
		// for simplicity not used in this example

		// inform ArchitectView about location changes
		if (architectView != null) {
			TEST_LATITUDE = (float) loc.getLatitude();
			TEST_LONGITUDE = (float) loc.getLongitude();
			TEST_ALTITUDE = (float) loc.getAltitude();
			architectView.setLocation(TEST_LATITUDE, TEST_LONGITUDE,
					TEST_ALTITUDE, loc.getAccuracy());
		}
	}

	@Override
	public void onProviderDisabled(String provider) {
		// TODO Auto-generated method stub
	}

	@Override
	public void onProviderEnabled(String provider) {
		// TODO Auto-generated method stub
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub
	}

	protected ArchitectView getArchitectView() {
		return architectView;
	}

	protected abstract void loadARWorld() throws IOException;

	// A work around for detecting the WIFI status because
	// isProviderEnabled(LocationManager.NETWORK_PROVIDER) always return true...
	private boolean wifiOrMobileProviderEnabled() {
		ConnectivityManager connectivity = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

		NetworkInfo[] nwInfos = connectivity.getAllNetworkInfo();
		boolean available = false;

		for (NetworkInfo nwInfo : nwInfos) {
			if (nwInfo.getTypeName() == null) {
				continue;
			}
			if ("wifi".equals(nwInfo.getTypeName().toLowerCase())) {
				available = nwInfo.isAvailable();
				if (available) {
					return available;
				}
			} else if ("mobile".equals(nwInfo.getTypeName().toLowerCase())) {
				available = nwInfo.isAvailable()
						&& nwInfo.getState() == NetworkInfo.State.CONNECTED;
				if (available) {
					return available;
				}
			}
		}

		return available;
	}

}